"""Helper functions and classes."""

import time
import functools
from typing import Any, Callable, Dict, Optional
from datetime import datetime


class Timer:
    """简单的计时器类。"""
    
    def __init__(self):
        self.start_time: Optional[float] = None
        self.end_time: Optional[float] = None
    
    def start(self) -> None:
        """开始计时。"""
        self.start_time = time.time()
        self.end_time = None
    
    def stop(self) -> float:
        """停止计时并返回耗时。
        
        Returns:
            耗时（秒）
        """
        if self.start_time is None:
            raise ValueError("Timer not started")
        
        self.end_time = time.time()
        return self.end_time - self.start_time
    
    def elapsed(self) -> float:
        """获取已经过的时间。
        
        Returns:
            已过时间（秒）
        """
        if self.start_time is None:
            raise ValueError("Timer not started")
        
        current_time = self.end_time or time.time()
        return current_time - self.start_time
    
    def __enter__(self):
        self.start()
        return self
    
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.stop()


def timing_decorator(func: Callable) -> Callable:
    """计时装饰器，打印函数执行时间。
    
    Args:
        func: 要装饰的函数
        
    Returns:
        装饰后的函数
    """
    @functools.wraps(func)
    def wrapper(*args, **kwargs):
        start_time = time.time()
        result = func(*args, **kwargs)
        end_time = time.time()
        print(f"{func.__name__} 执行时间: {end_time - start_time:.4f} 秒")
        return result
    return wrapper


def retry(max_attempts: int = 3, delay: float = 1.0, exceptions: tuple = (Exception,)):
    """重试装饰器。
    
    Args:
        max_attempts: 最大重试次数
        delay: 重试间隔（秒）
        exceptions: 需要重试的异常类型
        
    Returns:
        装饰器函数
    """
    def decorator(func: Callable) -> Callable:
        @functools.wraps(func)
        def wrapper(*args, **kwargs):
            last_exception = None
            
            for attempt in range(max_attempts):
                try:
                    return func(*args, **kwargs)
                except exceptions as e:
                    last_exception = e
                    if attempt < max_attempts - 1:
                        print(f"第 {attempt + 1} 次尝试失败: {e}，{delay} 秒后重试...")
                        time.sleep(delay)
                    else:
                        print(f"所有 {max_attempts} 次尝试都失败了")
            
            raise last_exception
        return wrapper
    return decorator


class Cache:
    """简单的内存缓存类。"""
    
    def __init__(self, max_size: int = 100):
        self.max_size = max_size
        self._cache: Dict[str, Any] = {}
        self._access_order: list = []
    
    def get(self, key: str) -> Optional[Any]:
        """获取缓存值。
        
        Args:
            key: 缓存键
            
        Returns:
            缓存值或None
        """
        if key in self._cache:
            # 更新访问顺序
            self._access_order.remove(key)
            self._access_order.append(key)
            return self._cache[key]
        return None
    
    def set(self, key: str, value: Any) -> None:
        """设置缓存值。
        
        Args:
            key: 缓存键
            value: 缓存值
        """
        if key in self._cache:
            # 更新现有键
            self._access_order.remove(key)
        elif len(self._cache) >= self.max_size:
            # 删除最久未访问的键
            oldest_key = self._access_order.pop(0)
            del self._cache[oldest_key]
        
        self._cache[key] = value
        self._access_order.append(key)
    
    def clear(self) -> None:
        """清空缓存。"""
        self._cache.clear()
        self._access_order.clear()
    
    def size(self) -> int:
        """获取缓存大小。
        
        Returns:
            缓存中的项目数量
        """
        return len(self._cache)


def format_timestamp(timestamp: Optional[float] = None, fmt: str = "%Y-%m-%d %H:%M:%S") -> str:
    """格式化时间戳。
    
    Args:
        timestamp: 时间戳，默认为当前时间
        fmt: 时间格式
        
    Returns:
        格式化后的时间字符串
    """
    if timestamp is None:
        timestamp = time.time()
    
    dt = datetime.fromtimestamp(timestamp)
    return dt.strftime(fmt)